package com.bitoon.basketdudes.web;

import com.bitoon.basketdudes.javamail.Mail;
import com.bitoon.basketdudes.web.datos.MensajeUsuario;
import com.bitoon.basketdudes.web.jpa.*;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import org.jdom.Document;
import org.jdom.Element;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.persistence.*;
import org.apache.log4j.Logger;

public class MiCuenta extends BaseAction {

    private Logger log = Logger.getLogger(MiCuenta.class);
    private Usuario usuarioLogado;
    private List<Pais> listaPaises;
    private List<TorneoUsuario> listaTorneos;

    // Mensajes
    private String[] mensaje; // Para recibir los ids del borrado de mensaje
                              // y el texto de contactar
    private String asunto;
    private String manager;

    private String urlRecarga = "/bd/jsp/recargar_bitoons.jsp";

    //private String email; // Para recordar contraseña

    private int exitoContactar; // indica si se ha grabado o no el mensaje

    // Mis Invitaciones
    private static int MAX_INVITACIONES = 5;
    private static int MAX_ID_USUARIO_CON_INVITACIONES = 3975; // 3975
    private String emailDestinatario;

    private String codigo_invitacion;
    private String email_invitacion;

    @Override
    public String execute() {
        EntityManager em = emfBasket.createEntityManager();
        log.debug("ejecutando MiCuenta");

        session.put("bd_ppp","ptcb");

        ValueStack valueStack = ActionContext.getContext().getValueStack();
        if (valueStack.findValue("stackUserLogado") != null) {
            Usuario u = (Usuario)valueStack.findValue("stackUserLogado");
            setUsuarioLogado(u);
            //setListaEquiposMostrar(u.getEquipos());

            // Buscar los torneos del usuario
            setListaTorneos(getListaTorneosUsuarioLogado());

            // Lee los mensajes del usuario
            if (getUsuarioLogado()!=null) {
                leerMensajesUsuario(getUsuarioLogado().getId());
            }

            // Ver si se envía el emailDestinatario

            //int numInvitaciones = getNumInvitacionesDisponibles();

            /*
            if (getUsuarioLogado().getId() > MAX_ID_USUARIO_CON_INVITACIONES) {
                numInvitaciones = 0;
            }
             * 
             */

            /*
            log.debug("invi - a");
            log.debug(email_invitacion);
            log.debug(codigo_invitacion);
             * 
             */

            /*
            if (email_invitacion!=null && codigo_invitacion!=null) {
                log.debug("invi - b");
                try {
                    em = emfBasket.createEntityManager();
                    em.getTransaction().begin();
                    Query q = em.createNamedQuery("Invitacion.findById");
                    q.setParameter("id",codigo_invitacion);
                    Invitacion i = (Invitacion)q.getSingleResult();

                    log.debug("usuario: " + i.getIdAmigo());
                    log.debug("invi - c: " + i);
                    log.debug("logado: " + getUsuarioLogado().getId());


                    if ((int)i.getIdAmigo()==getUsuarioLogado().getId()) {
                        // Mandar la invitacion al nuevo email
                        log.debug("invi - d");

                        i.setEmail(email_invitacion);
                        em.persist(i);
                        em.getTransaction().commit();

                        mandarInvitacion(i.getId(), email_invitacion);
                    } else {
                        log.debug(">>> el codigo de invitacion no es del usuario logado !!!");
                    }

                } catch (NoResultException nre) {
                } catch (Exception e) {
                    try { em.close(); } catch (Exception e2) { }
                    em.getTransaction().rollback();
                }
            }
             *
             */


            //if (emailDestinatario!=null && numInvitaciones > 0) {
            if (emailDestinatario!=null) {

                try {
                    em = emfBasket.createEntityManager();

                    if (esEmail(emailDestinatario)) {
                        log.debug("Invitacion para " + emailDestinatario);

                        /*
                        String pincode = "";
                        boolean invitacionExiste = true;

                        while (invitacionExiste) {
                            try {
                                pincode = generarPincode();
                                Query q = em.createNamedQuery("Invitacion.findById");
                                q.setParameter("id",pincode);
                                Invitacion i = (Invitacion)q.getSingleResult();
                            } catch (NoResultException nre) {
                                // No existe la invitación, es válida
                                invitacionExiste = false;
                            } catch (Exception e) {
                                log.error("Error", e);
                            }
                        }

                        log.debug("Encontrado pincode único: " + pincode);

                        // Grabarlo en la bd, y luego mandarlo por email

                        Anfitrion anfitrion = em.find(Anfitrion.class, 0);
                        Juego juego = em.find(Juego.class, 1);

                        Invitacion i = new Invitacion();
                        i.setId(pincode);
                        i.setAnfitrion(anfitrion);
                        i.setIdAmigo((Integer)getUsuarioLogado().getId());
                        i.setJuego(juego);
                        i.setEmail(emailDestinatario);

                        em.getTransaction().begin();
                        em.persist(i);
                        em.getTransaction().commit();

                         *
                         */
                        
                        // Mandar el email
                        mandarInvitacion("",emailDestinatario);

                        setMensajeAlerta("La invitación se ha enviado correctamente");

                    } else {
                        log.debug("No se ha introducido un mail correcto !!!");
                    }
                } catch (Exception e) {
                    log.error("Error, ", e);
                } finally {
                    try { em.close(); } catch (Exception e) { }
                }
            }

        }

        if (getIdUsuarioLogado() > 0) {
            return LOGADO;
        } else {
            return NO_LOGADO;
        }
    }

    public String mensajes() {
        String retorno = NO_LOGADO;
        if (getIdUsuarioLogado() > 0) {
            log.debug("Id: usuario" + getUsuarioLogado().getId());
            List<MensajeUsuario> mensajes = leerMensajesUsuario(getUsuarioLogado().getId());
            if (mensajes!=null) {
                setListaMensajes(mensajes);
                setNumMensajesBandejaEntrada(mensajes.size());
                session.put("mensajesLeidos", getListaMensajes());
            } else {
                setNumMensajesBandejaEntrada(0);
            }
            retorno = LOGADO;
        }
        return retorno;
    }


    private void mandarInvitacion(String pincode, String emailDestinatario) {

        String plantilla = configuracionGeneral.getProperty("plantillaMailInvitacion."+idioma);
        Scanner scanner = null;

        try {

            // Leer la plantilla
            FileInputStream fisp = new FileInputStream(new File(plantilla));
            scanner = new Scanner(fisp);
            StringBuilder contenidoPlantilla = new StringBuilder();

            while (scanner.hasNextLine()) {
                contenidoPlantilla.append(scanner.nextLine());
            }

            fisp.close();

            //nombreFicheroMailing = "C:/Proyectos/SistemaMailingComando/src/sistemaMailingComando/lista_mails.txt";

            Mail mail = new Mail();

            String contenido = contenidoPlantilla.toString();
            contenido = contenido.replace("[NOMBRE_USUARIO]", getUsuarioLogado().getNickMostrar());
            contenido = contenido.replace("[EMAIL_USUARIO]", emailDestinatario);
            contenido = contenido.replace("[PIN_CODE]", pincode);
            contenido = contenido.replace("[NICK_URL]", getUsuarioLogado().getNick());

            mail.sendMail(emailDestinatario, "Invitación a BasketDudes", contenido, true);
        } catch (FileNotFoundException fe) {
            System.out.println("El fichero no existe");
        } catch (Exception e) {
            System.out.println("Error: " + e);
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }



    private boolean esEmail(String email) {
        boolean retorno = false;

        try {
          Pattern p = Pattern.compile(".+@.+\\.[a-z]+");
          Matcher m = p.matcher(email);
          retorno = m.matches();
        } catch (Exception e) {
            log.error("Error en esMail", e);
        }

        return retorno;
    }



    private String generarPincode() {
        String pincode = "";
        String ALFABETO = "1234567890ACEFHJKLNPRTUXY";
        int longitud = 12;
        // 1YY8T1LPCKJA68

        for(int x=0; x<14; x++) {
            char c = ALFABETO.charAt((int)(Math.random()*ALFABETO.length()));
            pincode+=c;
        }

        return pincode;
    }
    

    public String recargar() {
        return SUCCESS;
    }

    public String borrarMensajes() {

        log.debug("borrando mensajes ... " + mensaje);

        String retorno = SUCCESS;

        for (String s : mensaje) {
            log.debug("Borrar el mensaje " + s);
            borrarMensajePorId(Integer.parseInt(s));
        }

        // Fijar la página de retorno a mensajes
        setUrlR(getText(getText("url.mi_cuenta.mis_mensajes")));

        return retorno;

    }

    public void borrarMensajePorId(int idMensaje) {

        try {
            Element nuevosMensajes = new Element("mensajes");
            Document nuevoDoc = new Document(nuevosMensajes);

            log.debug("nuevoDoc: " + nuevoDoc);

            Document doc = obtenerXMLMensajesUsuario(getUsuarioLogado().getId());
            if (doc != null) {
                List children = doc.getRootElement().getChildren();
                log.debug("chidren: " + children);
                Iterator iter = children.iterator();
                while (iter.hasNext()) {
                    Element child = (Element)iter.next();
                    if (child.getAttributeValue("id").equals(Integer.toString(idMensaje))) {
                        log.debug("id: " + idMensaje);
                    } else {
                        log.debug("Añadiendo " + child);
                        log.debug("nuevoDoc: " + nuevoDoc);
                        log.debug("name: " + child.getName());
                        iter.remove();
                        nuevoDoc.getRootElement().addContent(child);
                    }
                }

                log.debug("nuevoDoc.children: " +
                        nuevoDoc.getRootElement().getChildren());

                // Grabar el nuevo doc con el elemento borrado
                volcarDocAFichero(nuevoDoc, getUsuarioLogado().getId(),0);

                // Fijar otra vez los mensajes
                leerMensajesUsuario(getUsuarioLogado().getId());
                if (getListaMensajes()!=null) {
                    setNumMensajesBandejaEntrada(getListaMensajes().size());
                }
            }
        } catch (Exception e) {
            log.error("borrarMensajePorId: ",e);
        }

    }

    /*
     * Devuelve las listas en las que participa el usuario logado
     */
    public List<Network> getListaNetworksUsuario() {
        List<Network> retorno = null;
        List<EquipoNetwork> retorno1 = null;
        EntityManager em = null;

        log.debug("listaNetworksUsuario");

        try {
            int idUsuario = getIdUsuarioLogado();

            em = emfBasket.createEntityManager(); // checked

            /*Query q = em.createNativeQuery("select * from rankings.network n "
                    + "where n.creador = :idUsuario "
                    + "or n.id in ( "
                    + "select distinct(n.id) from rankings.ranking_network rn, "
                    + "rankings.network n, basket.equipo e "
                    + "where rn.equipo_id = e.id "
                    + "and rn.network_id = n.id "
                    + "and e.usuario_id = :idUsuario "
                    + ") order by n.nombre", Network.class);
            q.setParameter("idUsuario", idUsuario);
            retorno = (List<Network>)q.getResultList();*/

            Query q = em.createNamedQuery("Network.findByUsuarioId");
            q.setParameter("idUsuario", idUsuario);
            retorno = (List<Network>)q.getResultList();

            //ahora consultamos las networks de las que soy participe
            q = em.createNamedQuery("EquipoNetwork.findByIdUsuario");
            q.setParameter("idUsuario", idUsuario);
            retorno1 = (List<EquipoNetwork>)q.getResultList();

            //añado las  network a la lista retorno(conjunto de las network del usuario con las que participa)
            int id_newtwork; //nos sirve para saber si la siguiente network tenemos que meterla en la lista de retorno o no porque ya este dentro
            for(int i=0;i<retorno1.size();++i){
                if(!retorno.contains((Network)retorno1.get(i).getNetwork()) ){
                    retorno.add((Network)retorno1.get(i).getNetwork());
                }
            }

        } catch (Exception e) {
            log.error("[listaNetworksUsuario]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }



    public String contactar() {
        EntityManager em = null;
        String retorno = SUCCESS;

        setExitoContactar(0);

        try {
            em = emfBasket.createEntityManager(); // checked

            log.debug("Buscando a " + manager + " para contactar con el");
            
            Query q = em.createNamedQuery("Usuario.findById");
            q.setParameter("id", Integer.parseInt(manager));
            Usuario u = (Usuario)q.getSingleResult();

            log.debug("encontrado usuario: " + u);
            
            int exito = super.contactar(u.getId(), asunto, mensaje[0]);

            log.debug("exito[3]: " + exito);
            
            if (exito==0) {
                setExitoContactar(1); // El 1 es correcto para el Ajax de Carlos
            }
        } catch (NoResultException nre) {
            log.debug("El nick " + manager + " no se ha encontrado");
        } catch (Exception e) {
            log.error("[contactar]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }


    public List<TorneoUsuario> getListaTorneosUsuarioLogado() {
        List<TorneoUsuario> retorno = null;
        EntityManager em = null;

        try {
            em = emfBasket.createEntityManager(); // checked

            int idUsuario = getIdUsuarioLogado();

            Query q = em.createNamedQuery("Torneo.findByUsuarioId");
            q.setParameter("idUsuario", idUsuario);
            retorno = (List<TorneoUsuario>)q.getResultList();
        } catch (Exception e) {
            log.error("[getListaTorneosUsuarioLogado]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }


    public List<EquipoNetwork> getListaNetworksEquipo(int idEquipo) {
        List<EquipoNetwork> retorno = null;
        EntityManager em = null;
        try {
            int idUsuario = getIdUsuarioLogado();

            em = emfBasket.createEntityManager(); // checked

            Query q = em.createNamedQuery("EquipoNetwork.findByEquipoId");
            q.setParameter("idEquipo", idEquipo);
            retorno = (List<EquipoNetwork>)q.getResultList();
        } catch (Exception e) {
            log.error("[getListaNetworksEquipo]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }

    public List<RankingNetwork> getListaRankingsNetworkPorIdEquipo(int idEquipo) {
        List<RankingNetwork> retorno = null;
        EntityManager em = null;
        try {
            em = emfBasket.createEntityManager(); // checked

            Query q = em.createNamedQuery("RankingNetwork.findByEquipoId");
            q.setParameter("idEquipo", idEquipo);
            retorno = (List<RankingNetwork>)q.getResultList();
        } catch (Exception e) {
            log.error("[getListaRankingsNetworkPorIdEquipo]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }

    public int getNumInvitacionesDisponibles() {
        log.debug("getNumInvitacionesDisponibles");
        int retorno = MAX_INVITACIONES;

        List<Invitacion> misInvitaciones = getInvitacionesEmitidasUsuarioLogado();
        log.debug("misInvitaciones: " + misInvitaciones);
        if (misInvitaciones!=null) {
            retorno = retorno - misInvitaciones.size();
        }
        if (retorno < 0) {
            retorno = 0;
        }
        
        return retorno;
    }

    public List<Invitacion> getInvitacionesEmitidasUsuarioLogado() {
        List<Invitacion> retorno = null;
        EntityManager em = null;
        try {
            em = emfBasket.createEntityManager(); // checked

            Query q = em.createNamedQuery("Invitacion.findByAmigoId");
            q.setParameter("idAmigo", usuarioLogado.getId());
            retorno = (List<Invitacion>)q.getResultList();
        } catch (Exception e) {
            log.error("[getInvitacionesEmitidasUsuarioLogado]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }


    public List<Pais> getListaPaises() {
        setListaPaises();
        return listaPaises;
    }

    public void setListaPaises() {
        EntityManager em = null;

        try {
            em = emfBasket.createEntityManager(); // checked

            Query q = em.createNamedQuery("Pais.findAll");
            listaPaises = (List<Pais>)q.getResultList();
        } catch (Exception e) {
            log.error("[getListaPaises]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }
    }


    public List<RankingNetwork> getRankingNetworksUsuario(int idNetwork) {
        List<RankingNetwork> retorno = null;
        EntityManager em = null;

        try {
            int idUsuario = getIdUsuarioLogado();

            em = emfBasket.createEntityManager(); // checked

            Query q = em.createNamedQuery("RankingNetwork.findByIdUsuarioAndNetworkId");

            q.setParameter("idUsuario", idUsuario);
            q.setParameter("idNetwork", idNetwork);

            retorno = (List<RankingNetwork>)q.getResultList();
        } catch (Exception e) {
            log.error("[listaNetworksUsuario]: Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }

        return retorno;
    }

    /*
    public Usuario getUsuarioLogado() {
        return usuarioLogado;
    }
     * 
     */

    public void setUsuarioLogado(Usuario usuarioLogado) {
        this.usuarioLogado = usuarioLogado;
    }

    public List<String> getNombreMeses() {
        List<String> retorno = new ArrayList();
        GregorianCalendar gc = new GregorianCalendar();
        for(int x=0; x<12; x++) {
            gc.set(GregorianCalendar.MONTH, x);
            retorno.add(gc.getDisplayName(GregorianCalendar.MONTH,
                    GregorianCalendar.LONG, Locale.getDefault()));
        }
        return retorno;
    }

    public List<Integer> getListaAnyos() {
        List<Integer> retorno = new ArrayList();
        GregorianCalendar gc = new GregorianCalendar();

        for(int x=gc.get(GregorianCalendar.YEAR); x>gc.get(GregorianCalendar.YEAR)-100; x--) {
            retorno.add(x);
        }

        return retorno;
    }

    public List<TorneoUsuario> getListaTorneos() {
        return listaTorneos;
    }

    public void setListaTorneos(List<TorneoUsuario> listaTorneos) {
        this.listaTorneos = listaTorneos;
    }

    @Override
    public void setMensaje(String[] mensaje) {
        this.mensaje = mensaje;
    }

    @Override
    public void setAsunto(String asunto) {
        this.asunto = asunto;
    }

    public void setManager(String manager) {
        this.manager = manager;
    }

    public int getExitoContactar() {
        return exitoContactar;
    }

    public void setExitoContactar(int exitoContactar) {
        this.exitoContactar = exitoContactar;
    }

    public String getEmailDestinatario() {
        return emailDestinatario;
    }

    public void setEmailDestinatario(String emailDestinatario) {
        this.emailDestinatario = emailDestinatario;
    }

    public String getCodigo_invitacion() {
        return codigo_invitacion;
    }

    public void setCodigo_invitacion(String codigo_invitacion) {
        this.codigo_invitacion = codigo_invitacion;
    }

    public String getEmail_invitacion() {
        return email_invitacion;
    }

    public void setEmail_invitacion(String email_invitacion) {
        this.email_invitacion = email_invitacion;
    }

    public String getUrlRecarga() {
        String retorno = "/bd/jsp/recargar_bitoons.jsp";
        if (idioma.equals("en")) {
            retorno = "/bd/jsp/recargar_bitoons.jsp";
        }
        return urlRecarga;
    }

    public String getUrlRecargaNoLogado() {
        String retorno = "/login/recargar-bitoons/";
        if (idioma.equals("en")) {
            retorno = "/login/recharge-bitoons/";
        }
        return retorno;
    }

    public void setUrlRecarga(String urlRecarga) {
        this.urlRecarga = urlRecarga;
    }

}
